﻿using Opc.Ua;
using Opc.Ua.Client;
using SampleTcp;
using SHRIS.MIS.Common.Util.Extension;
using SHRIS.MIS.Entity.ScadaBaseInfo;
using SHRIS.MIS.Entity.ScadaData;
using SHRIS.MIS.Service.OpcService;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SHRIS.MIS.Service.Device
{
    public class ThreeCoordinatesMeasure_11 : BasicDevice
    {
        private readonly IEnumerable<OpcDataSourceEntity> _opcDataSourceEntities;

        private TcpListening tcpListener;

        private Guid opcServiceId;


        private MessageResponseContent messageResponseContent = new MessageResponseContent();


        public ThreeCoordinatesMeasure_11(DeviceEntity deviceEntity,
           WorkshopCommunicationService workshopCommunicationService,
           IEnumerable<OpcDataSourceEntity> opcDataSourceEntities)
           : base(deviceEntity, workshopCommunicationService)
        {
            _opcDataSourceEntities = opcDataSourceEntities;
            CheckOutDataType();
        }

        private void CheckOutDataType()
        {
            //对所有OPC 数据类型进行校验，如果不对记入LOG

        }


        public override void InitalDevice()
        {
            //创建opc 订阅  就分成一个通道，数据收集由LineManager完成


            //状态通道  程序号；状态  模式
            var subscriptionStatus = _opcDataSourceEntities.Where(i => i.DataAction == 4);
            //找出订阅数据的服务器列表
            var serverIds = subscriptionStatus.Select(i => i.ServerId).Distinct();


            if (serverIds.Count() == 1)
            {
                opcServiceId = serverIds.First();
                _workshopCommunicationService.CreateOpcSubscription(subscriptionStatus, DataHandler);
            }

            //创建tcp 监听
            //tcpListener = new TcpListening("192.168.1.235:11255");
            //tcpListener.TcpDataRecivedHandler += TcpListener_TcpDataRecivedHandler;
            //tcpListener.DoConnect();
        }

        

        private void DataHandler(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
        {
            try
            {
                MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
                //Console.WriteLine(notification.Value.StatusCode.ToString());

                if (notification != null)
                {
                    Guid dataId = new Guid();
                    bool isId = Guid.TryParse(monitoredItem.DisplayName, out dataId);
                    if (isId && (!dataId.IsGuidNullOrEmpty()))
                    {
                        var dataSource = _opcDataSourceEntities.Where(i => i.Id == dataId).First();
                        switch (dataSource.DataName)
                        {
                            case "BypassStatus":
                                {
                                    BypassStatus = (bool)notification.Value.Value;
                                    break;
                                }
                            case "Ready":
                                {
                                    Ready = (bool)notification.Value.Value;
                                    break;
                                }
                            case "End":
                                {
                                    End = (bool)notification.Value.Value;
                                    break;
                                }
                            case "HasWorkpiece":
                                {
                                    HasWorkpiece = (bool)notification.Value.Value;
                                    break;
                                }
                            case "WorkpieceSource":
                                {
                                    WorkpieceSource = (short)notification.Value.Value;
                                    break;
                                }
                            case "GetResult":
                                {
                                    GetResult = ((bool)notification.Value.Value).ToString()+"|"+notification.Value.SourceTimestamp;
                                    break;
                                }
                            case "MCode":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        MCode = notification.Value.Value.ToString();
                                    }
                                    break;
                                }
                            case "HandleMachine2":
                                {
                                    HandleMachine2 = (bool)notification.Value.Value;
                                    break;
                                }
                            case "HandleMachine3":
                                {
                                    HandleMachine3= (bool)notification.Value.Value;
                                    break;
                                }
                            case "ThreeEquStaW":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ushort _value = (ushort)notification.Value.Value;
                                        byte[] b = BitConverter.GetBytes(_value);
                                        ThreeEquStaW = new BitArray(b);
                                    }
                                    break;
                                }
                            case "ThreeEquProStaW":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ushort _value = (ushort)notification.Value.Value;
                                        byte[] b = BitConverter.GetBytes(_value);
                                        ThreeEquProStaW = new BitArray(b);
                                    }
                                    break;
                                }
                            case "ThreeEquAlarmW_1":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ushort _value = (ushort)notification.Value.Value;
                                        byte[] b = BitConverter.GetBytes(_value);
                                        ThreeEquAlarmW_1 = new BitArray(b);
                                    }
                                    break;
                                }
                            case "ThreeEquAlarmW_2":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ushort _value = (ushort)notification.Value.Value;
                                        byte[] b = BitConverter.GetBytes(_value);
                                        ThreeEquAlarmW_2 = new BitArray(b);
                                    }
                                    break;
                                }
                            case "ThreeEquActProNo":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ThreeEquActProNo = notification.Value.Value.ToString();
                                    }
                                    break;
                                }
                            case "ThreeEquMaterialCode":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ThreeEquMaterialCode = notification.Value.Value.ToString();
                                    }
                                    break;
                                }
                            case "ThreeEquStartEquTime":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ThreeEquStartEquTime = DateTimeOffset.Parse(notification.Value.Value.ToString());
                                    }
                                    break;
                                }
                            case "ThreeEquRunningTime":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ThreeEquRunningTime = Double.Parse(notification.Value.Value.ToString());
                                    }
                                    break;
                                }
                            case "ThreeResult":
                                {
                                    ThreeResult = (bool)notification.Value.Value;
                                    break;
                                }
                            case "ThreeValRequst":
                                {
                                    ThreeValRequst = (bool)notification.Value.Value;
                                    break;
                                }
                            case "ThreeValAct":
                                {
                                    ThreeValAct = (bool)notification.Value.Value;
                                    break;
                                }
                            case "ProductBatch":
                                {
                                    if (notification.Value.Value != null)
                                    {
                                        ProductBatch = notification.Value.Value.ToString();
                                    }
                                    break;
                                }
                            case "LoadFileFailed":
                                {
                                    LoadFileFailed = (bool)notification.Value.Value;
                                    break;
                                }
                            default:
                                {
                                    break;
                                }
                        }
                    }

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region 获取三坐标测量结果
        public List<string> GetThreeCoordinatesResult()
        {
            List<string> result = new List<string>();

            /**
             * 读取三坐标的21个检测项值
             */
            List<string> tags = new List<string>()
            {
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result1_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result2_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result3_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result4_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result5_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result6_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result7_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result8_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result9_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result10_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result11_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result12_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result13_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result14_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result15_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result16_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result17_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result18_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result19_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result20_1",
                "ns=2;s=Xibei01.MainPlcControl.ThreeCoordinatesMeasure.ProductionData.Result21_1"
            };

            try
            {
                List<DataValue> dataValues = _workshopCommunicationService.ReadValues(opcServiceId, tags);
                if (dataValues != null)
                {
                    for(int i = 0; i < dataValues.Count; i++)
                    {
                        if (dataValues[i] != null)
                        {
                            if (dataValues[i].Value != null)
                            {
                                result.Add(dataValues[i].Value.ToString());
                            }                           
                        }
                    }
                }
            }
            catch(Exception ex)
            {

            }
            return result;
        }

        #endregion

        #region 设备参数

        private bool loadFileFailed;
        /// <summary>
        /// 三坐标加载文件失败
        /// </summary>
        public bool LoadFileFailed
        {
            get
            {
                return loadFileFailed;
            }
            set
            {
                bool previewVlaue = loadFileFailed;
                loadFileFailed = value;
                OnPropertyChanged("LoadFileFailed", previewVlaue, loadFileFailed);
            }
        }

        private string productBatch;
        /// <summary>
        /// 产品批次
        /// </summary>
        public string ProductBatch
        {
            get
            {
                return productBatch;
            }
            set
            {
                string previewVlaue = productBatch;
                productBatch = value;
                OnPropertyChanged("ProductBatch", previewVlaue, productBatch);
            }
        }

        private BitArray threeEquStaW;
        /// <summary>
        /// 三坐标测量设备状态字
        /// DB7.DBB162
        /// </summary>
        public BitArray ThreeEquStaW
        {
            get
            {
                return threeEquStaW;
            }
            set
            {
                BitArray previewVlaue = threeEquStaW;
                threeEquStaW = value;
                OnPropertyChanged("ThreeEquStaW", previewVlaue, threeEquStaW);
            }
        }

        private BitArray threeEquProStaW;
        /// <summary>
        /// 三坐标测量程序状态字
        /// DB7.DBB164
        /// </summary>
        public BitArray ThreeEquProStaW
        {
            get
            {
                return threeEquProStaW;
            }
            set
            {
                BitArray previewVlaue = threeEquProStaW;
                threeEquProStaW = value;
                OnPropertyChanged("ThreeEquProStaW", previewVlaue, threeEquProStaW);
            }
        }

        private BitArray threeEquAlarmW_1;
        /// <summary>
        /// 三坐标测量设备报警字1
        /// DB7.DBB166
        /// </summary>
        public BitArray ThreeEquAlarmW_1
        {
            get
            {
                return threeEquAlarmW_1;
            }
            set
            {
                BitArray previewVlaue = threeEquAlarmW_1;
                threeEquAlarmW_1 = value;
                OnPropertyChanged("ThreeEquAlarmW_1", previewVlaue, threeEquAlarmW_1);
            }
        }

        private BitArray threeEquAlarmW_2;
        /// <summary>
        /// 三坐标测量设备报警字2
        /// DB7.DBB168
        /// </summary>
        public BitArray ThreeEquAlarmW_2
        {
            get
            {
                return threeEquAlarmW_2;
            }
            set
            {
                BitArray previewVlaue = threeEquAlarmW_2;
                threeEquAlarmW_2 = value;
                OnPropertyChanged("ThreeEquAlarmW_2", previewVlaue, threeEquAlarmW_2);
            }
        }

        private string threeEquActProNo;
        /// <summary>
        /// 三坐标测量当前程序号
        /// DB7.DBB170
        /// </summary>
        public string ThreeEquActProNo
        {
            get
            {
                return threeEquActProNo;
            }
            set
            {
                string previewVlaue = threeEquActProNo;
                threeEquActProNo = value;
                OnPropertyChanged("ThreeEquActProNo", previewVlaue, threeEquActProNo);
            }
        }

        private string threeEquMaterialCode;
        /// <summary>
        /// 物料码
        /// DB7.DBB202
        /// </summary>
        public string ThreeEquMaterialCode
        {
            get
            {
                return threeEquMaterialCode;
            }
            set
            {
                string previewVlaue = threeEquMaterialCode;
                threeEquMaterialCode = value;
                OnPropertyChanged("ThreeEquMaterialCode", previewVlaue, threeEquMaterialCode);
            }
        }

        private DateTimeOffset threeEquStartEquTime;
        /// <summary>
        /// 设备本次开机时刻
        /// DB7.DBB244
        /// </summary>
        public DateTimeOffset ThreeEquStartEquTime
        {
            get
            {
                return threeEquStartEquTime;
            }
            set
            {
                DateTimeOffset previewVlaue = threeEquStartEquTime;
                threeEquStartEquTime = value;
                OnPropertyChanged("ThreeEquStartEquTime", previewVlaue, threeEquStartEquTime);
            }
        }

        private double threeEquRunningTime;
        /// <summary>
        /// 三坐标开机时间，永不清零（单位:小时）
        /// DB7.DBD252
        /// </summary>
        public double ThreeEquRunningTime
        {
            get
            {
                return threeEquRunningTime;
            }
            set
            {
                double previewVlaue = threeEquRunningTime;
                threeEquRunningTime = value;
                OnPropertyChanged("ThreeEquRunningTime", previewVlaue, threeEquRunningTime);
            }
        }

        private bool threeResult;
        /// <summary>
        /// 测量结果是否超差（1=超差，0=无超差）
        /// DB7.DBX256
        /// </summary>
        public bool ThreeResult
        {
            get
            {
                return threeResult;
            }
            set
            {
                bool previewVlaue = threeResult;
                threeResult = value;
                OnPropertyChanged("ThreeResult", previewVlaue, threeResult);
            }
        }

        private bool threeValRequst;
        /// <summary>
        /// 请求反馈三坐标结果数据
        /// DB7.DBX256.1
        /// </summary>
        public bool ThreeValRequst
        {
            get
            {
                return threeValRequst;
            }
            set
            {
                bool previewVlaue = threeValRequst;
                threeValRequst = value;
                OnPropertyChanged("ThreeValRequst", previewVlaue, threeValRequst);
            }
        }

        private bool threeValAct;
        /// <summary>
        /// PC读取写入后=T，PC同时复位
        /// DB7.DBX256.2
        /// </summary>
        public bool ThreeValAct
        {
            get
            {
                return threeValAct;
            }
            set
            {
                bool previewVlaue = threeValAct;
                threeValAct = value;
                OnPropertyChanged("ThreeValAct", previewVlaue, threeValAct);
            }
        }


        private bool bypassStatus;
        public bool BypassStatus
        {
            get
            {
                return bypassStatus;
            }
            set
            {
                bool previewVlaue = bypassStatus;
                bypassStatus = value;
                OnPropertyChanged("BypassStatus", previewVlaue, bypassStatus);
            }
        }

        private bool ready;
        public bool Ready
        {
            get
            {
                return ready;
            }
            set
            {
                bool previewVlaue = ready;
                ready = value;
                OnPropertyChanged("Ready", previewVlaue, ready);
            }
        }

        private bool end;
        public bool End
        {
            get
            {
                return end;
            }
            set
            {
                bool previewVlaue = end;
                end = value;
                OnPropertyChanged("End", previewVlaue, end);
            }
        }

        private bool hasWorkpiece;
        public bool HasWorkpiece
        {
            get
            {
                return hasWorkpiece;
            }
            set
            {
                bool previewVlaue = hasWorkpiece;
                hasWorkpiece = value;
                OnPropertyChanged("HasWorkpiece", previewVlaue, hasWorkpiece);
            }
        }

        private short workpieceSource;
        public short WorkpieceSource
        {
            get
            {
                return workpieceSource;
            }
            set
            {
                short previewVlaue = workpieceSource;
                workpieceSource = value;
                OnPropertyChanged("WorkpieceSource", previewVlaue, workpieceSource);
            }
        }

        private string getResult;
        /// <summary>
        /// 获取三坐标的值提示
        /// 由于将这个提示发给LinePlantService后，记录到数据库需要用到时间，所以，该类型用string替代
        /// 格式：boolean|Datetime
        /// </summary>
        public string GetResult
        {
            get
            {
                return getResult;
            }
            set
            {
                string previewValue = getResult;
                getResult = value;
                OnPropertyChanged("GetResult", previewValue, getResult);
            }
        }

        private string mCode;
        /// <summary>
        /// 物料码
        /// </summary>
        public string MCode
        {
            get
            {
                return mCode;
            }
            set
            {
                string previewValue = mCode;
                mCode = value;
                OnPropertyChanged("MCode", previewValue, mCode);
            }
        }

        private bool handleMachine2;
        /// <summary>
        /// 物料来自车床2标识
        /// </summary>
        public bool HandleMachine2
        {
            get
            {
                return handleMachine2;
            }
            set
            {
                bool previewValue = handleMachine2;
                handleMachine2 = value;
                OnPropertyChanged("HandleMachine2", previewValue, handleMachine2);
            }
        }

        private bool handleMachine3;
        /// <summary>
        /// 物料来自车床3标识
        /// </summary>
        public bool HandleMachine3
        {
            get
            {
                return handleMachine3;
            }
            set
            {
                bool previewValue = handleMachine3;
                handleMachine3 = value;
                OnPropertyChanged("HandleMachine3", previewValue, handleMachine3);
            }
        }
        #endregion

        #region 三坐标TCP方法    暂时不用
        private void TcpListener_TcpDataRecivedHandler(object sender, TcpDataRecivedEventArgs e)
        {
            DecodeTcpResponse(e);
        }


        private void DecodeTcpResponse(TcpDataRecivedEventArgs e)
        {
            if(e.IpPort==tcpListener.ClientsIpPort)
            {

            }

            string[] ip = e.IpPort.Split(':');
            string data = e.ToString();
            string[] splitData = data.Split(':');
        }


        private string ParaseCommand(string command)
        {

            //102:e\chanpin\\aaa.ksln    打开检测文件
            //202： 设备是否空闲 1：空闲 0：不空闲
            //108:115:1047:-222
            //103:1


            string[] commands = command.Split(':');
            if (commands.Length == 2)
            {

                return "102:e" + "\\" + "chanpin" + "\\" + "\\" + "aaa.ksln";
            }
            else
                return command;
        }


        bool isSending = false;
        string currentCommand = "0";

        public async Task<string> SendCommand(string command, string data)
        {
            if(!isSending)
            {
                isSending = true;
                currentCommand = command;
                string message = currentCommand + ":" + data;
                tcpListener.SendData(message);
                await Task.Delay(1000);

                if(messageResponseContent.Command==currentCommand)
                {

                }

                currentCommand = "0";
                isSending = false;
                
            }
            return null;
        }

    }


    public class MessageResponseContent
    {

        /// <summary>
        /// command
        /// </summary>
        public string Command { get; set; } = "0";

        /// <summary>
        /// 答复内容
        /// </summary>
        public string ResponseData { get; set; }

        /// <summary>
        /// 答复时间
        /// </summary>
        public DateTime ResponseTime { get; set; }

    }
    #endregion

}
